﻿using FinalPointSet.Model.Asset;
using FinalPointSet.Model.Constant;
using FinalPointSet.Model.Model;
using FinalPointSet.Model.Model.FieldMapping;
using FinalPointSet.Model.Model.Knowledge;
using FinalPointSet.Model.Model.MockData;
using FinalPointSet.Model.Util;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Xml;
using static FinalPointSet.Model.Model.Knowledge.HighLight;

namespace FinalPointSet.Model.Manager
{
    public class AssetManager : SingletonBase<AssetManager>
    {
        #region 属性
        /// <summary>
        /// 单个Json对象资源
        /// </summary>
        private readonly Dictionary<Type, object> JsonObjectAssets = [];
        /// <summary>
        /// 单个Json对象资源的加载路径
        /// </summary>
        private readonly Dictionary<Type, string> JsonObjectPathAssets = [];
        /// <summary>
        /// Json集合对象资源
        /// </summary>
        private readonly Dictionary<Type, object> JsonObjectListAssets = [];
        /// <summary>
        /// Json集合对象资源的加载路径
        /// </summary>
        private readonly Dictionary<Type, string> JsonObjectListPathAssets = [];
        /// <summary>
        /// 对象资源
        /// </summary>
        private readonly Dictionary<Type, object> ObjectAssets = [];
        /// <summary>
        /// 对象资源的加载路径
        /// </summary>
        private readonly Dictionary<Type, string> ObjectPathAssets = [];
        /// <summary>
        /// 对象资源的生成器
        /// </summary>
        private readonly Dictionary<Type, object> ObjectGenerateAssets = [];
        /// <summary>
        /// 对象资源
        /// </summary>
        private readonly Dictionary<string, object> ObjectListAssets = [];
        /// <summary>
        /// 对象资源的加载路径
        /// </summary>
        private readonly Dictionary<string, string> ObjectListPathAssets = [];
        /// <summary>
        /// 对象资源的生成器
        /// </summary>
        private readonly Dictionary<string, object> ObjectListGenerateAssets = [];
        /// <summary>
        /// 文本集合资源
        /// </summary>
        private readonly Dictionary<string, List<TextPair>> TextListAssets = [];
        /// <summary>
        /// 文本集合资源的文件夹路径
        /// </summary>
        private readonly Dictionary<string, string> TextListPathAssets = [];
        #endregion

        #region 委托
        public delegate void OnJsonObjectListUpdateHandler(Type type);
        public event OnJsonObjectListUpdateHandler? OnJsonObjectListUpdate;
        #endregion

        #region 构造器 
        public AssetManager()
        {
            //加载知识点
            AddJsonObjectListAsset<DataSource>(Path.DataSource);
            AddJsonObjectListAsset<DataSourceMapping>(Path.DataSourceMapping, new DataSourceMappingConverter());
            AddJsonObjectListAsset<FormatTemplate>(Path.FormatTemplate, new FormatTemplateConverter());

            //加载自定义脚本
            AddJsonObjectListAsset<MockRule>(Path.MockRule);
            AddJsonObjectListAsset<MockFieldClassify>(Path.MockFieldClassify);
            AddJsonObjectListAsset<MockFieldMappingRule>(Path.MockFieldMappingRule);

            //加载代码高亮
            AddObjectListAsset(Path.HighLightDefinition, path =>
            {
                XmlReader reader = AssetUtil.FromXml(path);
                var xshd = HighlightingLoader.LoadXshd(reader);
                string fileName = AssetUtil.GetFileName(path);
                var fileValue = HighlightingLoader.Load(xshd, HighlightingManager.Instance);
                return new ObjectPair<IHighlightingDefinition>(fileName, fileValue);
            });
            AddJsonObjectAsset<KeywordMatchWorth>(Path.KeywordMatchWorth);

            // 加载代码高亮映射
            List<ObjectPair<IHighlightingDefinition>> highLightDefs = GetObjectList<IHighlightingDefinition>(Path.HighLightDefinition);
            AddJsonObjectListAsset<HighLight>(Path.HighLight, new HighLightConverter(highLightDefs));
            List<HighLight> highLights = GetJsonObjectList<HighLight>();

            //加载语言
            AddJsonObjectListAsset<Language>(Path.Language, new LanguageConverter(highLights));
            //获取对应集合
            List<Language> languages = GetJsonObjectList<Language>();
            //加载知识点
            AddJsonObjectListAsset<KnowledgePoint>(Path.KnowledgePoint, new KnowledgePointConverter(languages));

            //加载自定义参数
            AddJsonObjectListAsset<CustomParam>(Path.CustomParam);

            //加载图标集合
            AddFileNameTextListAssets(Path.LanguageLogo, Path.LanguageLogo);
            AddFileNameTextListAssets(Path.DataSourceLogo, Path.DataSourceLogo);

            //加载快捷键
            AddJsonObjectListAsset<HotKeyCombination>(Path.HotKeys);
        }
        #endregion

        #region JsonListAsset
        /// <summary>
        /// 注册Json集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        private void AddJsonObjectListAsset<T>(string path, JsonConverter? convert = null)
        {
            List<T>? jsonObjects = LoadJsonObjects<T>(path, convert);
            if (jsonObjects == null)
                return;
            if (JsonObjectListAssets.ContainsKey(typeof(T)))
            {
                JsonObjectListAssets[typeof(T)] = jsonObjects;
                JsonObjectListPathAssets[typeof(T)] = path;
            }
            else
            {
                JsonObjectListAssets.Add(typeof(T), jsonObjects);
                JsonObjectListPathAssets.Add(typeof(T), path);
            }
        }

        /// <summary>
        /// 从文件中加载Json集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        private static List<T>? LoadJsonObjects<T>(string path, JsonConverter? convert = null)
        {
            return JsonAssetLoader.GetObjects<T>(path, convert);
        }

        /// <summary>
        /// 从内存资源中获取对应类型的Json集合数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns></returns>
        public List<T> GetJsonObjectList<T>()
        {
            JsonObjectListAssets.TryGetValue(typeof(T), out var jsonObjectList);
            if (jsonObjectList is null)
            {
                return [];
            }
            else
            {
                return (List<T>)jsonObjectList;
            }
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="newList"></param>
        public void UpdateJsonObjectList<T>(List<T> newList)
        {
            if (newList == null)
                return;
            if (JsonObjectListAssets.ContainsKey(typeof(T)))
            {
                JsonObjectListAssets[typeof(T)] = newList;
            }
            //触发监听
            OnJsonObjectListUpdate?.Invoke(typeof(T));
        }

        /// <summary>
        /// 重新加载资源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void ReloadJsonObjectList<T>(JsonConverter? convert = null)
        {
            JsonObjectListPathAssets.TryGetValue(typeof(T), out string? jsonObjectListPath);
            if (jsonObjectListPath is null)
                return;
            AddJsonObjectListAsset<T>(jsonObjectListPath, convert);
        }

        /// <summary>
        /// 保存Json集合数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void SaveJsonObjectList<T>(JsonConverter? converter = null)
        {
            JsonObjectListPathAssets.TryGetValue(typeof(T), out string? path);
            List<T>? jsonObjectList = GetJsonObjectList<T>();
            if (jsonObjectList is null || path is null)
                return;
            JsonAssetLoader.SaveObjects(jsonObjectList, path, converter);
        }
        #endregion

        #region JsonObjectAsset
        private void AddJsonObjectAsset<T>(string path)
        {
            T? jsonObject = LoadJsonObject<T>(path);
            if (jsonObject == null)
                return;
            if (JsonObjectAssets.ContainsKey(typeof(T)))
            {
                JsonObjectAssets[typeof(T)] = jsonObject;
                JsonObjectPathAssets[typeof(T)] = path;
            }
            else
            {
                JsonObjectAssets.Add(typeof(T), jsonObject);
                JsonObjectPathAssets.Add(typeof(T), path);
            }
        }
        /// <summary>
        /// 从文件中加载Json资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        private static T? LoadJsonObject<T>(string path)
        {
            return JsonAssetLoader.GetObject<T>(path);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="newList"></param>
        public void UpdateJsonObject<T>(T obj)
        {
            if (obj == null)
                return;
            if (JsonObjectAssets.ContainsKey(typeof(T)))
            {
                JsonObjectAssets[typeof(T)] = obj;
            }
        }

        /// <summary>
        /// 从内存资源中获取对应类型的Json数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns></returns>
        public T? GetJsonObject<T>()
        {
            JsonObjectAssets.TryGetValue(typeof(T), out var jsonObject);
            if (jsonObject is null)
            {
                return default;
            }
            else
            {
                return (T)jsonObject;
            }
        }

        /// <summary>
        /// 重新加载资源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void ReloadJsonObject<T>()
        {
            JsonObjectPathAssets.TryGetValue(typeof(T), out string? jsonObjecPath);
            if (jsonObjecPath == null)
                return;
            AddJsonObjectAsset<T>(jsonObjecPath);
        }

        /// <summary>
        /// 保存Json数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void SaveJsonObjec<T>()
        {
            JsonObjectPathAssets.TryGetValue(typeof(T), out string? path);
            T? jsonObject = GetJsonObject<T>();
            if (jsonObject is null || path is null)
                return;
            JsonAssetLoader.SaveObject(jsonObject, path);
        }
        #endregion

        #region ObjectAsset
        /// <summary>
        /// 注册Json集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        private void AddObjectAsset<T>(string path, Func<string, T> generate)
        {
            T? obj = LoadObject(path, generate);
            if (obj == null)
                return;
            if (ObjectAssets.ContainsKey(typeof(T)))
            {
                ObjectAssets[typeof(T)] = obj;
                ObjectPathAssets[typeof(T)] = path;
                ObjectGenerateAssets[typeof(T)] = generate;
            }
            else
            {
                ObjectAssets.Add(typeof(T), obj);
                ObjectPathAssets.Add(typeof(T), path);
                ObjectGenerateAssets.Add(typeof(T), generate);
            }
        }

        /// <summary>
        /// 从文件中加载Json集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        private static T? LoadObject<T>(string path, Func<string, T> generate)
        {
            return ObjectAssetLoader.Generate(path, generate);
        }

        /// <summary>
        /// 从内存资源中获取对应类型的Json集合数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns></returns>
        public T? GetObject<T>()
        {
            ObjectAssets.TryGetValue(typeof(T), out var obj);
            if (obj is null)
            {
                return default;
            }
            else
            {
                return (T)obj;
            }
        }

        /// <summary>
        /// 重新加载资源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void ReloadObject<T>()
        {
            ObjectPathAssets.TryGetValue(typeof(T), out string? path);
            ObjectGenerateAssets.TryGetValue(typeof(T), out var generate);
            if (path is null || generate is null)
                return;
            Func<string, T> objGen = (Func<string, T>)generate;
            if (objGen is null)
                return;
            AddObjectAsset<T>(path, objGen);
        }
        #endregion

        #region ObjectListAsset
        /// <summary>
        /// 注册Json集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        private void AddObjectListAsset<T>(string dir, Func<string, ObjectPair<T>> generate)
        {
            List<ObjectPair<T>>? obj = LoadObjectList(dir, generate);
            if (obj == null)
                return;
            if (ObjectListAssets.ContainsKey(dir))
            {
                ObjectListAssets[dir] = obj;
                ObjectListPathAssets[dir] = dir;
                ObjectListGenerateAssets[dir] = generate;
            }
            else
            {
                ObjectListAssets.Add(dir, obj);
                ObjectListPathAssets.Add(dir, dir);
                ObjectListGenerateAssets.Add(dir, generate);
            }
        }

        /// <summary>
        /// 从文件中加载Json集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        private static List<ObjectPair<T>>? LoadObjectList<T>(string dir, Func<string, ObjectPair<T>> generate)
        {
            return ObjectAssetLoader.Generates(dir, generate);
        }

        /// <summary>
        /// 从内存资源中获取对应类型的Json集合数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns></returns>
        public List<ObjectPair<T>> GetObjectList<T>(string key)
        {
            ObjectListAssets.TryGetValue(key, out var objList);
            if (objList is null)
            {
                return new List<ObjectPair<T>>();
            }
            else
            {
                return (List<ObjectPair<T>>)objList;
            }
        }

        public ObjectPair<T>? GetObjectListElementByKey<T>(string key, string subKey)
        {
            List<ObjectPair<T>> result = GetObjectList<T>(key);
            if (result is null)
            {
                return new ObjectPair<T>();
            }
            return result.Find(e => e.Name.Equals(subKey, StringComparison.OrdinalIgnoreCase));
        }

        public T? GetObjectListElementValueByKey<T>(string key, string subKey)
        {
            ObjectPair<T>? pair = GetObjectListElementByKey<T>(key, subKey);
            return (pair != null) ? pair.Value : default;
        }
        #endregion

        #region StringListAssets
        /// <summary>
        /// 注册文本集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        private void AddTextListAssets(string key, string dir)
        {
            List<TextPair> textPairs = LoadTextListAssets(dir);
            if (textPairs == null)
                return;
            if (TextListAssets.ContainsKey(key))
            {
                TextListAssets[key] = textPairs;
                TextListPathAssets[key] = dir;
            }
            else
            {
                TextListAssets.Add(key, textPairs);
                TextListPathAssets.Add(key, dir);
            }
        }

        /// <summary>
        /// 从文件中加载文本集合资源
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        private static List<TextPair> LoadTextListAssets(string dir)
        {
            return TextAssetLoader.GetTextListPair(dir);
        }

        /// <summary>
        /// 从内存资源中获取对应类型的文本集合数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns></returns>
        public List<TextPair> GetTextList(string key)
        {
            TextListAssets.TryGetValue(key, out var textList);
            if (textList is null)
            {
                return [];
            }
            else
            {
                return textList;
            }
        }

        /// <summary>
        /// 添加文件夹内的文件名称到文本资源
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="dir">文件夹相对路径</param>
        public void AddFileNameTextListAssets(string key, string dir)
        {
            List<TextPair> textPairs = TextAssetLoader.GetDirectoryFileFullNames(dir);
            if (textPairs == null)
                return;
            //添加资源到字典
            TextListAssets.TryAdd(key, textPairs);
        }
        #endregion

    }
}
